#include <iostream>
using std::cout;
using std::endl;
using std::boolalpha;

template<class T, int kCapacity = 10>
class Stack{
public:
    Stack();
    ~Stack();

    bool empty() const;
    bool full() const;
    bool push(const T&);
//    T pop();
    bool pop(T& out_val);
    T top();
private:
    int _top;
    T* _data;
};
   
// 末班类的成员函数实现时必须包含模板参数列表
template<class T, int kCapacity>
Stack<T, kCapacity>::Stack()
    :_top(-1) ,_data(new T[kCapacity]){}

template<class T, int kCapacity>
Stack<T, kCapacity>::~Stack(){
    delete []_data;
}

template<class T, int kCapacity>
bool Stack<T, kCapacity>::empty() const{
    return _top == -1;
}

template<class T, int kCapacity>
bool Stack<T, kCapacity>::full() const{
    return _top == kCapacity - 1;
}

template<class T, int kCapacity>
bool Stack<T, kCapacity>::push(const T& data){
    if(full() == true) return false;
    _data[++_top] = data;
    return true;
}

template<class T, int kCapacity>
//T Stack<T, kCapacity>::pop(){
bool Stack<T, kCapacity>::pop(T& out_val){
    if(empty() == true) return false;
    //T data = top();
    out_val = _data[_top--];
    //return data;
    return true;
}

template<class T, int kCapacity>
T Stack<T, kCapacity>::top(){
    return _data[_top];
}

void test() {
    // 测试int类型栈
    Stack<int> intStack;
    cout << "intStack empty? " << boolalpha << intStack.empty() << endl; // true

    // 压入数据
    for(int i = 1; i <= 5; ++i) {
        if (intStack.push(i)) {  // 检查push是否成功
            cout << "Push success: " << i << ", Top: " << intStack.top() << endl;
        }
    }

    // 弹出数据（正确用法）
    int data;
    while(intStack.pop(data)) {  // 自动检查是否pop成功
        cout << "Pop success: " << data << endl;
    }

    // 测试空栈pop
    if (!intStack.pop(data)) {
        cout << "Correctly detected empty stack on pop" << endl;
    }

    // 测试满栈情况
    Stack<double, 3> dblStack;
    while(dblStack.push(1.23)) {  // 会自动停止在容量上限
        cout << "DblStack push success, now top: " << dblStack.top() << endl;
    }
    cout << "DblStack full? " << dblStack.full() << endl; // true
}

int main()
{
    test();
    return 0;
}

